﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace FCSChart.Graphical
{
    /// <summary>
    /// Y轴段选门
    /// </summary>
    public class SegmentYGraphical : BaseGraphical
    {
        private Point? y12;

        public Point? Y12
        {
            get { return y12; }
            private set { y12 = value; OnPropertyChanged("Y12"); }
        }

        public SegmentYGraphical() { }
        public SegmentYGraphical(SegmentYGraphicalModel model) : base(model)
        {
            this.Y12 = new Point(model.Y1, model.Y2);
            if (model.AreaNames != null && model.AreaNames.Count == 0)
            {
                Area = new GraphicalArea() { Name = model.AreaNames[0] };
                Helper.AddExistedGraphicalName(this.ShortName, model.AreaNames.ToArray());
                if (model.AreaColors != null && model.AreaColors.Count == 1)
                {
                    Area.DisplayColor = model.AreaColors[0];
                }
            }
        }
        protected override void InitName()
        {
            this.Name = "SegmentY";
            this.ShortName = "SY";
        }
        #region 容器事件--绘制图形时使用
        internal override void PanelMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (IsCreateing && sender is Panel panel)
            {
                var point = e.GetPosition(panel);
                var y = OwnerChart.YAxis.GetLocationValue(point.Y);
                Y12 = new Point(y, y);
            }
        }

        internal override void PanelMouseMove(object sender, MouseEventArgs e)
        {
            if (IsCreateing && sender is Panel panel)
            {
                var point = e.GetPosition(panel);
                var y = OwnerChart.YAxis.GetLocationValue(point.Y);
                if (Y12 != null) Y12 = new Point(y12.Value.X, y);

            }
        }

        internal override void PanelMouseUp(object sender, MouseButtonEventArgs e)
        {
            if (IsCreateing)
            {
                if (Y12.Value.X == Y12.Value.Y) return;
                IsCreateing = false;
            }
        }
        #endregion

        #region 图形移动变形

        internal override void Drawing()
        {
            if (OwnerChart == null || !OwnerChart.IsLoaded || OwnerChart.YAxis == null || !OwnerChart.YAxis.IsLoaded || OwnerChart.YAxis.ActualWidth == 0) return;
            if (GraphicalShape == null)
            {
                var temp = new Path() { Cursor = Cursors.Hand };
                temp.SetBinding(Path.DataProperty, new Binding("Y12") { Source = this, Converter = Converters.SegmentYPointsToGeometryConverter.Converter, ConverterParameter = this.OwnerChart, Mode = BindingMode.OneWay });

                temp.SetBinding(Shape.FillProperty, new Binding("Fill") { Source = this });
                temp.SetBinding(Shape.StrokeProperty, new Binding("Stroke") { Source = this });
                temp.SetBinding(Shape.StrokeThicknessProperty, new Binding("StrokeThickness") { Source = this });
                temp.SetBinding(FrameworkElement.ContextMenuProperty, new Binding("ContextMenu") { Source = this });
                temp.Focusable = true;
                temp.MouseDown += Graphical_MouseDown;
                temp.MouseMove += Graphical_MouseMove;
                temp.MouseLeftButtonUp += (sender, e) =>
                {
                    if (!IsCreateing) RefreshAreaSource(this.OwnerChart.XValueConverter, this.OwnerChart.YValueConverter);
                };
                temp.KeyDown += (sender, e) =>
                {
                    if (e.Key == Key.Up)
                    {
                        Move(0, -1); e.Handled = true;
                    }
                    else if (e.Key == Key.Down)
                    {
                        Move(0, 1); e.Handled = true;
                    }
                };
                GraphicalShape = temp;
            }
            OnPropertyChanged("Y12");
            if (!IsCreateing) DrawingControl();
        }
        internal override void Move(double x, double y)
        {
            if (y != 0)
            {
                var tempx = OwnerChart.YAxis.GetLocationValue(OwnerChart.YAxis.GetValueLocation(Y12.Value.X) + y);
                var tempy = OwnerChart.YAxis.GetLocationValue(OwnerChart.YAxis.GetValueLocation(Y12.Value.Y) + y);
                Y12 = new Point(tempx, tempy);
                DrawingControl();
            }
        }

        #endregion


        #region 门控制相关
        private GraphicalArea Area { get; set; }
        protected override void DrawingControl()
        {
            if (GraphicalShape is Path graphical && graphical.Data is PathGeometry geometry && geometry.Figures.Count == 1 && geometry.Figures[0].Segments.Count == 4)
            {
                if (Area == null) Area = new GraphicalArea() { Name = OwnerChart.CreateNewAreaNameFunction(this) };
                this.OwnerChart.AddGraphicalArea(Area);
                List<Point> points = new List<Point>();
                for (int i = 0; i < 2; i++)
                {
                    var segment = geometry.Figures[0].Segments[i] as LineSegment;
                    var point = new Point(segment.Point.X / 2, segment.Point.Y);
                    points.Add(point);
                    if (ControlShapes.Count > i)
                    {
                        if (ControlShapes[i] is Path path && path.Data is EllipseGeometry ellipse)
                            ellipse.Center = point;
                    }
                    else
                    {
                        ControlShapes.Add(new Path() { Data = new EllipseGeometry(point, 5, 5), Cursor = Cursors.SizeNS });
                    }
                }
                Area.Center = new Point(points.Average(p => p.X), points.Average(p => p.Y));
            }
        }

        protected override void Shape_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed && sender is Path path && path.Data is EllipseGeometry ellipse)
            {
                var point = e.GetPosition(OwnerChart.ViewPanel);
                var index = ControlShapes.IndexOf(path);
                var value = OwnerChart.YAxis.GetLocationValue(point.Y);
                if (index == 0) Y12 = new Point(value, y12.Value.Y);
                else Y12 = new Point(y12.Value.X, value);
                e.Handled = true;
                ellipse.Center = point;
            }
        }

        protected override void Shape_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            DrawingControl();
            base.Shape_MouseLeftButtonUp(sender, e);
        }
        protected override void Shape_MouseLeave(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed) DrawingControl();
            base.Shape_MouseLeave(sender, e);
        }
        #endregion
        /// <summary>
        /// 更新门划分的区域内数据
        /// </summary>
        internal override async void RefreshAreaSource(Func<object, double> xValueConverter, Func<object, double> yValueConverter)
        {
            if (Area == null) return;
            if (!isCreateing && Y12.HasValue && OwnerChart != null && OwnerChart.YSource != null)
            {
                var min = Math.Min(Y12.Value.X, Y12.Value.Y);
                var max = Math.Max(Y12.Value.X, Y12.Value.Y);
                var items = OwnerChart.YSource;
                var count = items.Count;
                var parentIndexs = OwnerChart.Indexs;

                var maxDegreeOfParallelism = OwnerChart.Series == null ? 4 : OwnerChart.Series.MaxDegreeOfParallelism;
                Area.InsideIndexs = await Task.Run(() =>
                {
                    ConcurrentBag<int> indexs = new ConcurrentBag<int>();
                    if (parentIndexs == null)
                    {
                        var result = Parallel.For(0, count, new ParallelOptions() { MaxDegreeOfParallelism = maxDegreeOfParallelism }, (i) =>
                        {
                            var v = yValueConverter == null ? Convert.ToDouble(items[i]) : yValueConverter(items[i]);
                            if (v >= min && v <= max) indexs.Add(i);
                        });
                    }
                    else
                    {
                        var result = Parallel.ForEach(parentIndexs, new ParallelOptions() { MaxDegreeOfParallelism = maxDegreeOfParallelism }, (i) =>
                        {
                            var v = yValueConverter == null ? Convert.ToDouble(items[i]) : yValueConverter(items[i]);
                            if (v >= min && v <= max) indexs.Add(i);
                        });
                    }
                    return indexs.ToArray();
                });
            }
            else
            {
                Area.InsideIndexs = null;
            }
        }
        /// <summary>
        /// 获取门的数据类型
        /// </summary>
        /// <returns></returns>
        protected override BaseGraphicalModel GetGraphicalMode()
        {
            if (IsCreateing) return null;
            return new SegmentYGraphicalModel() { AreaNames = new string[] { Area.Name }, AreaColors = new Color[] { Area.DisplayColor }, Y1 = Y12.Value.X, Y2 = Y12.Value.Y };
        }

        public override void Dispose()
        {
            base.Dispose();
            if (Area != null)
            {
                if (this.OwnerChart != null) this.OwnerChart.RemoveGraphicalArea(Area);
                Area = null;
            }
        }
    }

    public class SegmentYGraphicalModel : BaseGraphicalModel
    {
        public double Y1 { get; set; }
        public double Y2 { get; set; }
    }
}
